<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>[1.16]-配置读取：内外网环境配置的完美切换 | PhalApi(π框架) - PHP轻量级开源接口框架 - 助你创造价值！</title>
    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
    <meta content="yes" name="apple-mobile-web-app-capable">
    <meta content="black" name="apple-mobile-web-app-status-bar-style">
    <meta content="telephone=no" name="format-detection">
    <meta content="email=no" name="format-detection">
    <meta name="Author" content="PhalApi,ecitlm,dogstar">
    <meta name="description" content="[1.16]-配置读取：内外网环境配置的完美切换，PhalApi是一个PHP轻量级开源接口框架，致力于快速开发接口服务。支持HTTP/SOAP/RPC等协议，可用于搭建接口/微服务/RESTful接口/Web Services。我们不断更新，保持生气；为接口负责，为开源负责！并承诺永久免费！">
    <meta name="keywords" content="PhalApi,phalapi,phalapi接口开发,后台接口开发,后台接口开发框架,接口开发,接口框架,开源接口框架,PHP后台接口开发,PHP接口开发,PHP接口框架,PHP后台接口框架,phalapi官网,PHP接口框架,php接口开发框架,php接口开发,php web框架,π框架,π开发框架,π接口框架,π接口开发框架,api接口,php接口,,PHP接口框架,phalapi文档,phalapi wiki,PhalApi文档,phalapi在线文档,phalapi官方文档">

    <link rel="stylesheet" type="text/css" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" media="screen">
    <link rel="stylesheet" type="text/css" href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.css" media="screen">
    <link rel="stylesheet" href="../css/main.css" />
    <link rel="stylesheet" href="../css/loading_bar.css" />
    <link rel="icon" href="http://webtools.qiniudn.com/dog_catch.png" type="image/x-icon" />
    <script src="../js/pace.min.js"></script>
	
	<!-- 代码高亮 -->
	<link rel="stylesheet" href="../css/highlight.min.css">
	<script src="../js/highlight.min.js"></script>
	<script>hljs.initHighlightingOnLoad();</script>
    
</head>

<body>
    <!-- navbar start -->
    <div class="navbar navbar-default navbar-fixed-top" id="mainnav" role="navigation">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand website_name" href="/"><!-- <span>PhalApi</span> --><strong></strong></a>
            </div>
            <div class="navbar-collapse collapse" aria-expanded="false" style="height: 1px;">
                <ul class="nav navbar-nav navbar-right" id="nav_bar">
                    <li><a href="https://www.phalapi.net/"><span class="glyphicon glyphicon-home"></span></a></li>
                    <li><a href="https://www.phalapi.net/download.html">下载</a></li>
                    <li class="active"><a href="https://www.phalapi.net/wikis/">文档</a></li>
                    <li><a href="https://www.phalapi.net/donate.html">贡献</a></li>
                    <li><a href="#">|</a></li>
                    <li><a href="http://qa.phalapi.net/" target="_blank">社区</a></li>
                    <li><a href="http://www.ituring.com.cn/book/2405" target="_blank">书籍</a></li>
                    <li><a href="http://demo.phalapi.net/listAllApis.php" target="_blank">体验</a></li>
                    <li><a href="https://github.com/phalapi/phalapi-library" target="_blank">扩展</a></li>
                </ul>
            </div>
            <!--/.nav-collapse -->
        </div>
    </div>
    <!-- navbar end -->


    <div id="content">
        <div class="container">
            <div class="row row-md-flex row-md-flex-wrap">
                <h4><a href="/wikis/%5B1.15%5D-%E6%95%B0%E6%8D%AE%E5%BA%93%E6%93%8D%E4%BD%9C%EF%BC%9A%E5%9F%BA%E4%BA%8ENotORM%E7%9A%84%E4%BD%BF%E7%94%A8%E5%8F%8A%E4%BC%98%E5%8C%96.html">上一章</a>   <a href="/wikis/">文档首页</a>   <a href="/wikis/%5B1.17%5D-%E6%97%A5%E8%AE%B0%E7%BA%AA%E5%BD%95%EF%BC%9A%E7%AE%80%E5%8C%96%E7%89%88%E7%9A%84%E6%97%A5%E8%AE%B0%E6%8E%A5%E5%8F%A3.html">下一章</a></h4>
<hr />
<p><em>Experience by itself teaches nothing... Without theory, experience has no meaning. Without theory, one has no questions to ask. Hence, without theory, there is no learning. – Edwards Deming</em>  </p>
<h2>1.16.1 配置的简单读取</h2>
<p>通常，我们会有以下三个配置文件：  </p>
<pre><code class="language-bash">dogstar@ubuntu:Config$ tree
.
├── app.php
├── dbs.php
└── sys.php
</code></pre>
<p>其中app.php为项目应用配置；dbs.php为分布式存储的数据库配置；sys.php为不同环境下的系统配置。  </p>
<p>在入口文件，注册配置组件服务后：</p>
<pre><code class="language-bash">//$ vim ./Public/init.php

//配置
DI()-&gt;config = new PhalApi_Config_File(API_ROOT . '/Config');</code></pre>
<p>假设有这样的app.php配置：</p>
<pre><code class="language-php">return array(

    'version' =&gt; '1.1.1',

    'email' =&gt; array(
        'address' =&gt; 'chanzonghuang@gmail.com',
    );
);
</code></pre>
<p>我们就可以分别这样根据需要获取配置：</p>
<pre><code class="language-php">//app.php里面的全部配置
DI()-&gt;config-&gt;get('app');

//app.php里面的单个配置
DI()-&gt;config-&gt;get('app.version');  //返回：1.1.1

//app.php里面的多级配置
DI()-&gt;config-&gt;get('app.email.address');  //返回：'chanzonghuang@gmail.com'</code></pre>
<p>其他配置文件类似，你也可以随意添加新的配置文件。</p>
<h2>1.16.2 内外环境配置管理的策略</h2>
<p>可以说，在项目开发中，除了我们的代码、数据和文档外，配置也是一块相当重要的组成部分，而且占据着非常重要的位置。最为明显的是，如果配置一旦出错，就很可能影响到整个系统的运行，并且远比修改代码再上线发布速度快（假设我们不用文件存储配置而是以分布式存储在各服务器内存中）。  </p>
<p>但这里将讨论另外一个同样重要的问题，即： <strong>不同环境下不同配置的管理和切换</strong> 。  </p>
<p>现在将不同的策略分说如下。</p>
<h3>(1)支持整包发布的环境变量配置</h3>
<p>此种策略的主要方法就是在PHP代码中读取php-fpm中的ENV环境配置，再对应到linux环境下的profile环境变量，即：</p>
<pre><code>PHP代码  --&gt;    $_ENV环境配置  --&gt;   Linux服务器环境变量/etc/profile</code></pre>
<p>例如：  </p>
<pre><code>&lt;?php

return array(
    /**
     * DB数据库服务器集群
     */
    'servers' =&gt; array(
        'db_demo' =&gt; array(                         //服务器标记
            'host'      =&gt; $_ENV['PHALPI_DB_HOST'],             //数据库域名
            'name'      =&gt; $_ENV['PHALPI_DB_NAME'],               //数据库名字
            'user'      =&gt; $_ENV['PHALPI_DB_USER'],                  //数据库用户名
            'password'  =&gt; $_ENV['PHALPI_DB_PASSWORD'],                     //数据库密码
            'port'      =&gt; $_ENV['PHALPI_DB_PORT'],                  //数据库端口
            'charset'   =&gt; $_ENV['PHALPI_DB_CHARSET'],                  //数据库字符集
        ),
    ),
);</code></pre>
<p>接着，在php-fpm.ini文件中，添加相应的配置：  </p>
<pre><code>env[PHALPI_DB_HOST]='localhost'
env[PHALPI_DB_NAME]='phalapi'
env[PHALPI_DB_USER]='root'
env[PHALPI_DB_PASSWORD]=''
env[PHALPI_DB_PORT]='3306'
env[PHALPI_DB_CHARSET]='UTF8'</code></pre>
<p>最后，重启php-fpm即可。  </p>
<p>这样的好处莫过于可以支持项目代码的整包发布，而不需要在各个环境（开发环境、测试环境、回归环境、预发布环境、生产环境）来回修改切换配置，同时运维可以更好地保护服务器的账号和密码而不让开发知道。</p>
<p>而这样的不足则是，在对项目进行初次部署时，需要添加以上一系列的配置，而且后期维护也比较复杂麻烦，特别当机器多时。这时可以通过pupple/stacksalt这些运维工具进行自动化管理。但对于开发来说，依然会觉得有点烦锁。</p>
<h3>(2)不同环境，不同入口</h3>
<p>当服务器的账号和密码也是由开发来掌控时，则可以使用这种在代码层次控制的策略。  </p>
<p>我们可以在Public下提供不同的入口，一如：</p>
<pre><code class="language-bash">$ mkdir ./Public/myapi
$ myapi$ tree
.
├── index.php
└── test.php
</code></pre>
<p>我们有这样不同的入口，客户端在测试时，只需要将入口路径改成：/myapi/test.php?service=XXX.XXX，而在打包发布时只需要将入口路径改成：/myapi/?service=XXX.XXX 即可。也就是将test.php去掉。  </p>
<p>而在服务端，仅需要在这些不同的入口文件，修改一下配置文件目录路径即可：</p>
<pre><code class="language-php">//$ vim ./Public/myapi/test.php
DI()-&gt;config = new PhalApi_Config_File(API_ROOT . '/ConfigTest');</code></pre>
<p>另外，也可以通过客户端在请求时带参数来作区分，如带上&amp;env=test或者&amp;env=prod。</p>
<h3>(3)持续集成下的配置管理</h3>
<p>但个人最为建议的还是在 <strong>持续集成</strong> 下作配置管理。  </p>
<p>因为首先，持续集成中的发布应该是经常性的，且应该是自动化的。所以，既然有自动化的支持，我们也应该及早地将配置纳入其中管理。</p>
<p>配置文件不同只要是环境不同，而环境不同所影响的配置文件通常只有sys.php和dbs.php；为此，我们为测试环境和生产环境准备了各自的配置文件，而在发布时自动选择所需要的配置文件。一般地，我们建议生产环境的配置文件以 <strong>.prod</strong> 结尾。所以，这时我们的配置文件可能会是这样：</p>
<pre><code class="language-bash">dogstar@ubuntu:Config$ tree
.
├── app.php
├── dbs.php
├── dbs.php.prod
├── sys.php
└── sys.php.prod</code></pre>
<p>多了生产环境的配置文件：dbs.php.prod和sys.php.prod。  </p>
<p>再通过发布工具，我们就可以对不同环境的配置文件进行快速选择了。这里以phing为例，说明一下相关的配置和效果。  </p>
<p>如下，在Phing的配置文件build.xml中，在生产环境发布过程中，我们将配置文件进行了替换。</p>
<pre><code class="language-xml">//$ vim ./build.xml 

        &lt;copy 
            file="./Config/dbs.php.prod" 
            tofile="./Config/dbs.php" 
            overwrite="true" /&gt;
        &lt;copy 
            file="./Config/sys.php.prod" 
            tofile="./Config/sys.php" 
            overwrite="true" /&gt;</code></pre>
<p>执行phing发布后，将会看到对应的这样提示：</p>
<pre><code class="language-bash">     [copy] Copying 1 file to /home/phapapi/Config
     [copy] Copying 1 file to /home/phapapi/Config</code></pre>
<h3>(4) 更灵活的配置覆盖管理方式</h3>
<p>还有一种相当于<code>.env</code>形式的配置管理方式。即添加一个dbs.php.prod文件，但不需要复制全部的配置，只需要配置待覆盖的配置即可。例如，不同环境下，有不同的数据库配置。可以：  </p>
<pre><code>// $ vim ./Config/dbs.php.prod
&lt;?php

return array(
    /**
     * DB数据库服务器集群
     */
    'servers' =&gt; array(
        'db_demo' =&gt; array(                         //服务器标记
            'host'      =&gt; '192.168.1.101',             //数据库域名（仅数据库HOST、用户名、密码不同）
            'user'      =&gt; 'apps',                  //数据库用户名
            'password'  =&gt; '123456',                        //数据库密码
        ),
    ),
);</code></pre>
<p>然后，在dbs.php文件添加上面配置并覆盖原来的即可，如：  </p>
<pre><code>&lt;?php
$rs = return array(
    // 原来的配置...
);

if (file_exists(dirname(__FILE__) . '/dbs.php.prod')) {
    $rs = array_replace_recursive($rs, include(dirname(__FILE__) . '/dbs.php.prod')));
}

return $rs;</code></pre>
<p>这样，就可以通过新增一个dbs.php.prod文件，并且此文件是不纳入代码版本管理了，便可实现部署时的配置管理。</p>
<h2>1.16.3 主从数据库的配置</h2>
<p>通常一般而言，数据库支持分表分库配置，且只有一份，即：  </p>
<pre><code class="language-bash">./Config/dbs.php</code></pre>
<p>然后，我们这样指定数据库的配置：  </p>
<pre><code class="language-php">DI()-&gt;notorm = function() {
    $debug = !empty($_GET['__sql__']) ? true : false;
    return new PhalApi_DB_NotORM(DI()-&gt;config-&gt;get('dbs'), $debug);
};</code></pre>
<p>如果需要从库时，可以参考./Config/dbs.php，创建一个从库的配置拷贝，即：</p>
<pre><code class="language-bash">cp ./Config/dbs.php ./Config/dbs_slave.php</code></pre>
<p>然后，注册一个从库的notorm：</p>
<pre><code class="language-php">DI()-&gt;notormSlave = function() {
    $debug = !empty($_GET['__sql__']) ? true : false;
    return new PhalApi_DB_NotORM(DI()-&gt;config-&gt;get('dbs_slave'), $debug); //注意：配置不同
};</code></pre>
<p>最后使用此从库的服务DI()-&gt;notormSlave即可完成对从库的读取操作，用法同DI()-&gt;notorm，这里不再赘述。</p>
<h2>1.16.4 扩展你的配置读取</h2>
<p>虽然上面有不同的配置文件管理策略，但很多实际情况下，我们的配置需要可以随时更改、下发和调整。并且在海量访问，性能要求高的情况下快速读取配置。  </p>
<p>这就要求我们的项目既可以方便维护即时修改，又需要能够快速同步一致更新下发和读取。这样就涉及到了配置更高层的管理：  统一集中式的配置管理，还是分布式的配置管理？  文件存储，还是DB存储，还是MC缓存，还是进驻内存？    </p>
<p>个人认为，性能最优的莫过于配置进驻内存并分布式存储。毕竟作为前端机的PHP内存这块还是相对充裕且可以利用的。但需要把这一条线打通，有点难度。  </p>
<p>这里不过多地谈论配置更多的内容，但在PhalApi框架中，当你根据自己项目的需要实现了自己的配置读取方式后，再次简单的在入口文件重新注册即可。</p>
<h2>1.16.5 使用Yaconf扩展快速读取配置</h2>
<p>首先，非常感谢 @豹 同学的提议：使用Yaconf扩展快速读取配置。  </p>
<p>虽然现在是冬天，有点冷（特别是在北京的同学），而且现在还是凌晨1点25分。但我们希望能继续将开源的热情继续下去。  </p>
<p>以下是刚刚这几个小时努力的成果。  </p>
<h3>(1)前期准备：PHP7 的安装</h3>
<p>具体可以参考：<a href="http://blog.csdn.net/21aspnet/article/details/47708763">Linux环境PHP7.0安装 </a>  </p>
<h3>(2)前期准备：Yaconf扩展的安装</h3>
<p>具体可以参考：<a href="https://github.com/laruence/yaconf">laruence/yaconf</a>  </p>
<h3>(3)使用</h3>
<p>和正常的配置一样，简单如下：  </p>
<pre><code class="language-php">DI()-&gt;config = new PhalApi_Config_Yaconf();

var_dump(DI()-&gt;config-&gt;get('foo')); //相当于var_dump(Yaconf::get("foo"));

var_dump(DI()-&gt;config-&gt;has('foo')); //相当于var_dump(Yaconf::has("foo"));</code></pre>
<p>以上，假设我们已经有了这样的配置文件：  </p>
<pre><code class="language-bash">$ vim ./test.ini
name="PhalApi"
version="1.3.1"</code></pre>
<p>需要注意的是，如果需要使用Yaconf扩展，需要PHP7的版本支持，但使用基本上和原来PhalApi的思路是完全一样的。<br />
但还有所区别的是，配置文件的目录路径（当然也可以配置成和PhalApi的配置目录一致）、以及配置文件的格式。  </p>
<p>Just have fun!</p>
<hr />
<h4><a href="/wikis/%5B1.15%5D-%E6%95%B0%E6%8D%AE%E5%BA%93%E6%93%8D%E4%BD%9C%EF%BC%9A%E5%9F%BA%E4%BA%8ENotORM%E7%9A%84%E4%BD%BF%E7%94%A8%E5%8F%8A%E4%BC%98%E5%8C%96.html">上一章</a>   <a href="/wikis/">文档首页</a>   <a href="/wikis/%5B1.17%5D-%E6%97%A5%E8%AE%B0%E7%BA%AA%E5%BD%95%EF%BC%9A%E7%AE%80%E5%8C%96%E7%89%88%E7%9A%84%E6%97%A5%E8%AE%B0%E6%8E%A5%E5%8F%A3.html">下一章</a></h4><div style="float: left">
<h4>
<a href="http://qa.phalapi.net/">还有疑问？欢迎到社区提问！</a>
&nbsp;&nbsp;
<a href="http://docs.phalapi.net/#/v2.0/">切换到PhalApi 2.x 开发文档。</a>
</h4>
</div>
            </div>
        </div>
    </div>

 <!-- 广告位 -->
<div class="grid-wrapper desktop-only">
	<p align="center">
		<a href="http://7xiz2f.com1.z0.glb.clouddn.com/%E6%88%91%E7%9A%84%E5%90%8D%E5%AD%97%E5%8F%AB%EF%BC%9A%CF%80%E6%A1%86%E6%9E%B6%20-%20PhalApi%202016%E5%B9%B4%E5%BA%A6%E5%BC%80%E6%BA%90%E6%80%BB%E7%BB%93%20-%20%E5%AE%98%E6%96%B9%E5%87%BA%E5%93%81.pdf" target="blank"><img width="950" height="100" src="http://7xiz2f.com1.z0.glb.clouddn.com/ad_20170104.png"></a>
		<a href="http://www.itran.cc/" target="blank"><img width="950" height="100" src="http://7xslqv.com1.z0.glb.clouddn.com/images/9/69/b88bc92455dc1239f9a5bf8d72929.png"></a>
		<a href="http://web-tools.phalapi.net/" target="blank"><img width="950" height="100" src="http://7xslqv.com1.z0.glb.clouddn.com/images/7/d0/88f523566c482296aecc43d185ca2.png"></a>
	</p>
</div>

        <!-- footer -->
        <div class="footer">
            <div class="link container ">
                <div class=" col-xs-7 col-sm-7 col-md-7 col-lg-7 ">
                    <h3>PhalApi (π框架)</h3>
                    <p>一个轻量级PHP开源接口框架，专注于接口服务开发，支持HTTP/SOAP/RPC协议，拥有自动生成的在线文档、多种开发语言的客户端SDK包以及可重用的扩展类库，可用于快速搭建微服务、RESTful接口或Web
                        Services。</p>
                    <!-- <p>:</p> -->
                    <a href="https://www.phalapi.net/" target="_blank"> PhalApi </a>
                    <span>|</span>
                    <a href="http://qa.phalapi.net/" target="_blank">社区</a>
                    <span>|</span>
                    <a href="download.html" target="_blank">下载</a>
                    <span>|</span>
                    <a href="/wikis/">文档</a>
                    <span>|</span>
                    <a href="http://www.ituring.com.cn/book/2405" target="_blank">书籍</a>
                    <span>|</span>
                    <a href="http://demo.phalapi.net/listAllApis.php" target="_blank">体验</a>
                    <span>|</span>
                    <a href="donate.html" target="_blank">贡献</a>
                    <span>|</span>
                    <a href="https://github.com/phalapi/phalapi-library" target="_blank">扩展</a>
                    <span>|</span>
                    <a href="/license.html" target="_blank">许可</a>
                    <span>|</span>
                    <a href="/about.html" target="_blank">关于</a>
                    <span>|</span>
                    <a href="https://www.phalapi.net/wikis/en/" target="_blank">English</a>

                </div>
                <div class=" col-xs-5 col-sm-5 col-md-5 col-lg-5 contact_us ">
                    <h3>联系我们</h3>
                    <a href="https://github.com/phalapi/phalapi"><img src="../images/github.png" alt="github" /></a>
                    <a href="http://weibo.com/p/100808d236e99beb645bfb56ed1c37dde9b8bd?k=phalapi%E5%BC%80%E6%BA%90%E6%A1%86%E6%9E%B6&from=501&_from_=huati_topic"><img src="../images/weibo.png"  alt="weibo" /></a>
                    <a href="http://7xslqv.com1.z0.glb.clouddn.com/images/1/b0/894fde762850cb11250253f7d5ede.png"><img src="../images/zfb.png"  alt="zfb" /></a>
					<a target="_blank" href="//shang.qq.com/wpa/qunwpa?idkey=f16292029e59975d4ccfccc70ed87aa5c5646df512e83b0e9e1270e8368be461"><img border="0" src="images/qq.png" alt="π框架 - PhalApi交流群②" title="π框架 - PhalApi交流群②"></a>
					<a href="http://git.oschina.net/dogstar/PhalApi"><img src="../images/git-oschina.png"  alt="git-oschina" /></a>
                </div>
                <div class="cls"></div>
                <div class="text-center copy_right"> ©2015-2017 PhalApi All Rights Reserved. <a href="http://www.miitbeian.gov.cn" target="_blank">粤ICP备15028808号</a>

				<script type="text/javascript">var cnzz_protocol = (("https:" == document.location.protocol) ? " https://" : " http://");document.write(unescape("%3Cspan id='cnzz_stat_icon_1255326144'%3E%3C/span%3E%3Cscript src='" + cnzz_protocol + "s4.cnzz.com/z_stat.php%3Fid%3D1255326144%26show%3Dpic' type='text/javascript'%3E%3C/script%3E"));</script>
                </div>
            </div>
        </div>
    </div>


    <a href="https://github.com/phalapi"><img id="gitHub_fllow" style="position: fixed; top: 0; right: 0; border: 0;z-index:9999" src="https://camo.githubusercontent.com/652c5b9acfaddf3a9c326fa6bde407b87f7be0f4/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6f72616e67655f6666373630302e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png"></a>


    <script src="../js/jquery-1.11.1.min.js"></script>
    <script src="../js/bootstrap.min.js"></script>
</body>

</html>